{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Log-likelihood benchmark\n",
    "\n",
    "This is a simple benchmark, which I use for basic test of vector-based computing engines.\n",
    "\n",
    "The problem is to find log-likelihood of normal distribution:\n",
    "$\\sum_i \\log \\left[ \\dfrac{1}{\\sqrt{2 \\pi \\sigma}} \\exp \\left( - \\dfrac{(x_i - x)^2}{2 \\sigma^2} \\right) \\right] $\n",
    "\n",
    "There are elementwise subtraction, division, power, exponent, logarithm and summation of array, so this is broader test.\n",
    "\n",
    "tested: \n",
    "0. numpy + scipy's pdf\n",
    "1. numpy\n",
    "2. cython\n",
    "4. numexpr\n",
    "3. theano\n",
    "4. parakeet\n",
    "5. C++\n",
    "6. FORTRAN\n",
    "\n",
    "computing log-likelihood for normal distribution \n",
    "\n",
    "__Notes__\n",
    "1. Not optimizing computations here (but in theory theano and parakeet may remove unnecessary computations)\n",
    "2. This test includes exp, log, division and summation of array\n",
    "2. Everything is running on CPU in one thread, this limitation is for 'fairness' of tests\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import numpy\n",
    "import scipy\n",
    "from scipy.stats import norm\n",
    "import theano"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Scipy implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def llh_scipy(data, mean, sigma):\n",
    "    lh = norm(mean, sigma).pdf(data)\n",
    "    return numpy.log(lh).sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numpy implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def llh_numpy(data, mean, sigma):\n",
    "    s = (data - mean) ** 2 / (2 * (sigma ** 2))\n",
    "    pdfs = numpy.exp(- s)\n",
    "    pdfs /= numpy.sqrt(2 * numpy.pi) * sigma\n",
    "    return numpy.log(pdfs).sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cython implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "%load_ext Cython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "%%cython\n",
    "cdef extern from \"math.h\":\n",
    "    double sqrt(double m)\n",
    "    double exp(double m)\n",
    "    double log(double m)\n",
    "\n",
    "import cython\n",
    "import numpy as np\n",
    "\n",
    "cimport numpy as np\n",
    "from numpy cimport ndarray\n",
    "pi = np.pi\n",
    "\n",
    "@cython.boundscheck(False)\n",
    "@cython.wraparound(False)\n",
    "def llh_cython(ndarray[np.float64_t, ndim=1] data, double mean, double sigma):\n",
    "    cdef int l = len(data)\n",
    "    cdef double llh = 0\n",
    "    cdef double s = 0\n",
    "    for i in xrange(l):\n",
    "        s = (data[i] - mean) ** 2 / (2 * (sigma ** 2))\n",
    "        llh += log(exp(-s) / (sqrt(2 * pi) * sigma))\n",
    "    return llh"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numexpr implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import numexpr\n",
    "numexpr.set_num_threads(1)\n",
    "\n",
    "def llh_numexpr(data, mean, sigma):\n",
    "    expression = 'sum(log(exp(- (data-mean) **2  / (2 * sigma ** 2)) / (sqrt(2 * pi) * sigma)))'\n",
    "    return numexpr.evaluate(expression, local_dict=dict(data=data, mean=mean, sigma=sigma, pi=numpy.pi))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Parakeet implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import parakeet\n",
    "parakeet.config.backend = 'c'\n",
    "\n",
    "@parakeet.jit \n",
    "def llh_parakeet(data, mean, sigma):\n",
    "    s = (data - mean) ** 2 / (2 * (sigma ** 2))\n",
    "    pdfs = numpy.exp(- s)\n",
    "    pdfs /= numpy.sqrt(2 * numpy.pi) * sigma\n",
    "    return numpy.log(pdfs).sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Theano implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cpu\n"
     ]
    }
   ],
   "source": [
    "import theano\n",
    "import theano.tensor as T\n",
    "\n",
    "print theano.config.device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "theano.config.openmp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def llh_theano(data, mean, sigma):\n",
    "    s = (data - mean) ** 2 / (2 * (sigma ** 2))\n",
    "    pdfs = T.exp(- s)\n",
    "    pdfs /= T.sqrt(2 * numpy.pi) * sigma\n",
    "    return T.log(pdfs).sum()\n",
    "\n",
    "mean, sigma = T.scalars('m', 's')\n",
    "d = T.vector('data')\n",
    "\n",
    "llh_theano = theano.function([d, mean, sigma], llh_theano(d, mean, sigma))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## FORTRAN implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "$.getScript(\"https://raw.github.com/marijnh/CodeMirror/master/mode/fortran/fortran.js\", function () {\n",
       "IPython.config.cell_magic_highlight['magic_fortran'] = {'reg':[/^%%fortran/]};});\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%load_ext fortranmagic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "%%fortran \n",
    "subroutine llh_fortran(data, mean, sigma, result)\n",
    "    real*8, dimension(:), intent(in) :: data\n",
    "    real*8, intent(in) :: mean, sigma\n",
    "    real*8, intent(out) :: result\n",
    "            \n",
    "    real*8, dimension(size(data, 1)) :: s\n",
    "    real*8, parameter :: PI = 3.14159265358979323846\n",
    "\n",
    "    s = (data - mean) ** 2 / (2 * sigma ** 2)\n",
    "    s = exp(- s) / (sqrt(2 * PI) * sigma)\n",
    "    result = sum(log(s))\n",
    "    \n",
    "end subroutine llh_fortran"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## C++ implementation for comparison of speed\n",
    "we are neither passing, nor returning anything in c++. Just doing same operations in C++ for some array to compare speed.\n",
    "\n",
    "Mind the overhead for creating new process - it is essential for small sizes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting test_speed.cpp\n"
     ]
    }
   ],
   "source": [
    "%%writefile test_speed.cpp\n",
    "#include <iostream>\n",
    "#include <stdio.h>\n",
    "#include <stdlib.h>\n",
    "#include <math.h>\n",
    "\n",
    "// using namespace std;\n",
    "\n",
    "\n",
    "int main(int argc, char** argv) {\n",
    "    if (argc < 4){\n",
    "        std::cout << \"run with n_samples, mean, sigma!\";\n",
    "        return 1;\n",
    "    }\n",
    "    int size = atoi(argv[1]);\n",
    "    double mean = atof(argv[2]);\n",
    "    double sigma = atof(argv[3]);\n",
    "    \n",
    "    double * data = new double[size];\n",
    "    double factor = 1. / size;\n",
    "    for (int i=0; i<size; ++i){\n",
    "        data[i] = i * factor;\n",
    "    }\n",
    "    double result = 0.;\n",
    "    double s = 0.;\n",
    "    double x = 0.;\n",
    "    \n",
    "    for (int i=0; i<size; ++i){\n",
    "        x = (data[i] - mean);\n",
    "        s =  x * x / (2 * (sigma * sigma));\n",
    "        result += log(exp(-s) / (sqrt(2 * M_PI) * sigma));\n",
    "    }\n",
    "    \n",
    "    std::cout << std::endl << result << std::endl;\n",
    "    return 0;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "!g++ test_speed.cpp -o test_speed -O3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def llh_cpp(data, mean, sigma):\n",
    "    size = len(data)\n",
    "    out = !./test_speed {len(data)} {mean} {sigma}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data generation, checking that all functions output the same value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from collections import OrderedDict\n",
    "functions = OrderedDict()\n",
    "functions['scipy'] = llh_scipy\n",
    "functions['numpy'] = llh_numpy\n",
    "functions['cython'] = llh_cython\n",
    "functions['numexpr'] = llh_numexpr\n",
    "functions['parakeet'] = llh_parakeet\n",
    "functions['theano'] = llh_theano\n",
    "functions['fortran'] = llh_fortran\n",
    "functions['c++'] = llh_cpp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "scipy -1431841.8928\n",
      "numpy -1431841.8928\n",
      "cython -1431841.8928\n",
      "numexpr -1431841.8928\n",
      "parakeet -1431841.8928\n",
      "theano -1431841.8928\n",
      "fortran -1431841.90671\n",
      "c++ None\n"
     ]
    }
   ],
   "source": [
    "data = numpy.random.normal(size=1000000).astype('float64')\n",
    "for name, function in functions.items():\n",
    "    print name, function(data, 0.1, 1.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100 loops, best of 3: 11.2 ms per loop\n",
      "100 loops, best of 3: 6 ms per loop\n",
      "100 loops, best of 3: 10.8 ms per loop\n",
      "100 loops, best of 3: 7.14 ms per loop\n",
      "100 loops, best of 3: 6.54 ms per loop\n",
      "100 loops, best of 3: 8.07 ms per loop\n",
      "100 loops, best of 3: 6.03 ms per loop\n",
      "100 loops, best of 3: 16.6 ms per loop\n",
      "10 loops, best of 3: 134 ms per loop\n",
      "10 loops, best of 3: 62.2 ms per loop\n",
      "10 loops, best of 3: 108 ms per loop\n",
      "10 loops, best of 3: 71 ms per loop\n",
      "10 loops, best of 3: 63.4 ms per loop\n",
      "10 loops, best of 3: 81.7 ms per loop\n",
      "10 loops, best of 3: 57.1 ms per loop\n",
      "10 loops, best of 3: 83 ms per loop\n",
      "1 loops, best of 3: 1.82 s per loop\n",
      "1 loops, best of 3: 857 ms per loop\n",
      "1 loops, best of 3: 1.08 s per loop\n",
      "1 loops, best of 3: 713 ms per loop\n",
      "1 loops, best of 3: 660 ms per loop\n",
      "1 loops, best of 3: 877 ms per loop\n",
      "1 loops, best of 3: 639 ms per loop\n",
      "1 loops, best of 3: 694 ms per loop\n",
      "1 loops, best of 3: 19.8 s per loop\n",
      "1 loops, best of 3: 9.01 s per loop\n",
      "1 loops, best of 3: 11.1 s per loop\n",
      "1 loops, best of 3: 7.12 s per loop\n",
      "1 loops, best of 3: 6.44 s per loop\n",
      "1 loops, best of 3: 8.54 s per loop\n",
      "1 loops, best of 3: 6.39 s per loop\n",
      "1 loops, best of 3: 6.88 s per loop\n"
     ]
    }
   ],
   "source": [
    "import timeit \n",
    "sizes = [10 ** 5, 10 ** 6, 10 ** 7, 10 ** 8]\n",
    "import pandas\n",
    "scores = pandas.DataFrame(data=0, columns=functions.keys(), index=sizes)\n",
    "for size in sizes:\n",
    "    for name, function in functions.items():\n",
    "        data = numpy.random.normal(size=size).astype('float64')\n",
    "        result = %timeit -o function(data, 0.1, 1.1)\n",
    "        scores.loc[size, name] = result.best"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Results (time in seconds, less is better) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>scipy</th>\n",
       "      <th>numpy</th>\n",
       "      <th>cython</th>\n",
       "      <th>numexpr</th>\n",
       "      <th>parakeet</th>\n",
       "      <th>theano</th>\n",
       "      <th>fortran</th>\n",
       "      <th>c++</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>100000   </th>\n",
       "      <td>  0.011209</td>\n",
       "      <td> 0.006000</td>\n",
       "      <td>  0.010787</td>\n",
       "      <td> 0.007137</td>\n",
       "      <td> 0.006539</td>\n",
       "      <td> 0.008067</td>\n",
       "      <td> 0.006031</td>\n",
       "      <td> 0.016596</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1000000  </th>\n",
       "      <td>  0.134079</td>\n",
       "      <td> 0.062242</td>\n",
       "      <td>  0.108327</td>\n",
       "      <td> 0.071049</td>\n",
       "      <td> 0.063404</td>\n",
       "      <td> 0.081651</td>\n",
       "      <td> 0.057135</td>\n",
       "      <td> 0.083036</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10000000 </th>\n",
       "      <td>  1.823849</td>\n",
       "      <td> 0.857088</td>\n",
       "      <td>  1.078784</td>\n",
       "      <td> 0.713240</td>\n",
       "      <td> 0.659757</td>\n",
       "      <td> 0.876672</td>\n",
       "      <td> 0.638656</td>\n",
       "      <td> 0.694401</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>100000000</th>\n",
       "      <td> 19.826547</td>\n",
       "      <td> 9.006766</td>\n",
       "      <td> 11.110369</td>\n",
       "      <td> 7.124668</td>\n",
       "      <td> 6.436616</td>\n",
       "      <td> 8.542589</td>\n",
       "      <td> 6.389464</td>\n",
       "      <td> 6.884255</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               scipy     numpy     cython   numexpr  parakeet    theano  \\\n",
       "100000      0.011209  0.006000   0.010787  0.007137  0.006539  0.008067   \n",
       "1000000     0.134079  0.062242   0.108327  0.071049  0.063404  0.081651   \n",
       "10000000    1.823849  0.857088   1.078784  0.713240  0.659757  0.876672   \n",
       "100000000  19.826547  9.006766  11.110369  7.124668  6.436616  8.542589   \n",
       "\n",
       "            fortran       c++  \n",
       "100000     0.006031  0.016596  \n",
       "1000000    0.057135  0.083036  \n",
       "10000000   0.638656  0.694401  \n",
       "100000000  6.389464  6.884255  "
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "scores"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comparison to numpy time (less is better)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "normalized_scores = scores.copy()\n",
    "for column in normalized_scores.columns:\n",
    "    normalized_scores[column] /= scores['numpy']    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>scipy</th>\n",
       "      <th>numpy</th>\n",
       "      <th>cython</th>\n",
       "      <th>numexpr</th>\n",
       "      <th>parakeet</th>\n",
       "      <th>theano</th>\n",
       "      <th>fortran</th>\n",
       "      <th>c++</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>100000   </th>\n",
       "      <td> 1.868104</td>\n",
       "      <td> 1</td>\n",
       "      <td> 1.797846</td>\n",
       "      <td> 1.189456</td>\n",
       "      <td> 1.089899</td>\n",
       "      <td> 1.344443</td>\n",
       "      <td> 1.005108</td>\n",
       "      <td> 2.765994</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1000000  </th>\n",
       "      <td> 2.154161</td>\n",
       "      <td> 1</td>\n",
       "      <td> 1.740413</td>\n",
       "      <td> 1.141503</td>\n",
       "      <td> 1.018674</td>\n",
       "      <td> 1.311835</td>\n",
       "      <td> 0.917955</td>\n",
       "      <td> 1.334087</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10000000 </th>\n",
       "      <td> 2.127960</td>\n",
       "      <td> 1</td>\n",
       "      <td> 1.258662</td>\n",
       "      <td> 0.832166</td>\n",
       "      <td> 0.769766</td>\n",
       "      <td> 1.022849</td>\n",
       "      <td> 0.745146</td>\n",
       "      <td> 0.810186</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>100000000</th>\n",
       "      <td> 2.201295</td>\n",
       "      <td> 1</td>\n",
       "      <td> 1.233558</td>\n",
       "      <td> 0.791035</td>\n",
       "      <td> 0.714642</td>\n",
       "      <td> 0.948464</td>\n",
       "      <td> 0.709407</td>\n",
       "      <td> 0.764343</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              scipy  numpy    cython   numexpr  parakeet    theano   fortran  \\\n",
       "100000     1.868104      1  1.797846  1.189456  1.089899  1.344443  1.005108   \n",
       "1000000    2.154161      1  1.740413  1.141503  1.018674  1.311835  0.917955   \n",
       "10000000   2.127960      1  1.258662  0.832166  0.769766  1.022849  0.745146   \n",
       "100000000  2.201295      1  1.233558  0.791035  0.714642  0.948464  0.709407   \n",
       "\n",
       "                c++  \n",
       "100000     2.765994  \n",
       "1000000    1.334087  \n",
       "10000000   0.810186  \n",
       "100000000  0.764343  "
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "normalized_scores"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "Many libraries claim that they can speed up number crunching in python.\n",
    "Results of this test are floating (+- 0.1), but what we can see\n",
    "1. numpy turned out to be fastest at moderate sizes of arrays\n",
    "2. numpy implementation at least not more complex than others\n",
    "3. parakeet was the only to get sensible speed up"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Technical info"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "16 xeon cores\n"
     ]
    }
   ],
   "source": [
    "import multiprocessing\n",
    "print multiprocessing.cpu_count(), 'xeon cores'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.10.1'"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "numpy.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0.14.0'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "scipy.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0.21.1'"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import cython\n",
    "cython.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2.4'"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "numexpr.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0.23.2'"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "parakeet.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0.7.0'"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "theano.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using built-in specs.\r\n",
      "COLLECT_GCC=g++\r\n",
      "COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper\r\n",
      "Target: x86_64-linux-gnu\r\n",
      "Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu\r\n",
      "Thread model: posix\r\n",
      "gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) \r\n"
     ]
    }
   ],
   "source": [
    "!g++ -v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using built-in specs.\r\n",
      "COLLECT_GCC=gfortran\r\n",
      "COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper\r\n",
      "Target: x86_64-linux-gnu\r\n",
      "Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu\r\n",
      "Thread model: posix\r\n",
      "gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) \r\n"
     ]
    }
   ],
   "source": [
    "!gfortran -v"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
